package com.rem.rabbitmq.boot.Adelay;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 使用死信队列实现 延迟队列
 *
 * @author Rem
 * @date 2021-12-29
 */

@Configuration
public class QueueConfig {

    /**
     * 普通交换机 队列 routingKey
     */
    public static final String X_EXCHANGE = "X";

    public static final String XA_ROUTING_KEY = "XA";

    public static final String XB_ROUTING_KEY = "XB";

    public static final String QA_QUEUE = "QA";

    public static final String QB_QUEUE = "QB";

    public static final String XC_ROUTING_KEY = "XC";

    public static final String QC_QUEUE = "QC";


    /**
     * 死信交换机 队列 routingKey
     */
    public static final String Y_DEAD_EXCHANGE = "Y";

    public static final String YD_DEAD_ROUTING_KEY = "YD";

    public static final String QD_DEAD_QUEUE = "QD";


    /*********************************普通队列QA*********************************************************/
    /**
     * 声明普通交换机X
     *
     * @return
     */
    @Bean("xExchange")
    public DirectExchange xExchange() {
        return new DirectExchange(X_EXCHANGE);
    }

    /**
     * 声明普通队列QA并且绑定死信交换机
     *
     * @return
     */
    @Bean("queueA")
    public Queue queueA() {
        /**
         * 手动设置参数
         */
       /* Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", Y_DEAD_EXCHANGE);
        arguments.put("x-dead-letter-routing-key", YD_DEAD_ROUTING_KEY);
        arguments.put("x-message-ttl", 10000);
        return QueueBuilder.durable(QA_QUEUE).withArguments(arguments).build();*/
        /**
         * 根据内置api设置参数 过期时间 ms
         */
        return QueueBuilder.durable(QA_QUEUE)
                .deadLetterExchange(Y_DEAD_EXCHANGE).deadLetterRoutingKey(YD_DEAD_ROUTING_KEY).ttl(10000).build();
    }

    /**
     * 普通交换机与普通队列QA通过 普通routingKey XA 绑定
     *
     * @param queueA
     * @param xExchange
     * @return
     */
    @Bean
    public Binding queueaBindingX(@Qualifier("queueA") Queue queueA, @Qualifier("xExchange") DirectExchange xExchange) {
        return BindingBuilder.bind(queueA).to(xExchange).with(XA_ROUTING_KEY);
    }

    /*********************************普通队列QB*********************************************************/

    /**
     * 声明普通队列QB 并且绑定死信交换机
     *
     * @return
     */
    @Bean("queueB")
    public Queue queueB() {
        /**
         * 根据内置api设置参数
         */
        return QueueBuilder.durable(QB_QUEUE)
                .deadLetterExchange(Y_DEAD_EXCHANGE).deadLetterRoutingKey(YD_DEAD_ROUTING_KEY).ttl(40000).build();
    }

    /**
     * 普通交换机与普通队列通过QB 普通routingKey 绑定
     *
     * @param queueB
     * @param xExchange
     * @return
     */
    @Bean
    public Binding queuebBindingX(@Qualifier("queueB") Queue queueB, @Qualifier("xExchange") DirectExchange xExchange) {
        return BindingBuilder.bind(queueB).to(xExchange).with(XB_ROUTING_KEY);
    }


    /*********************************死信队列QD*********************************************************/


    /**
     * 声明死信交换机Y
     *
     * @return
     */
    @Bean("yExchange")
    public DirectExchange yExchange() {
        return new DirectExchange(Y_DEAD_EXCHANGE);
    }

    /**
     * 声明死信队列
     *
     * @return
     */
    @Bean("queueD")
    public Queue queueD() {
        return new Queue(QD_DEAD_QUEUE);
    }

    /**
     * 死信交换机与死信队列通过 死信routingKey XA 绑定
     *
     * @param queueD
     * @param yExchange
     * @return
     */
    @Bean
    public Binding deadLetterBindingY(@Qualifier("queueD") Queue queueD, @Qualifier("yExchange") DirectExchange yExchange) {
        return BindingBuilder.bind(queueD).to(yExchange).with(YD_DEAD_ROUTING_KEY);
    }


    /*********************************普通队列QC*********************************************************/

    /**
     * 声明普通队列QC 并且绑定死信交换机
     * 不设置过期时间 交给生产方设置
     * *因为RabbitMQ只会检查第一个消息是否过期，如果过期则丢到死信队列，如果第一个消息的延时时长很长，
     * *而第二个消息的延时时长很短，第二个消息并不会优先得到执行。
     *
     * @return
     */
    @Bean("queueC")
    public Queue queueC() {
        /**
         * 根据内置api设置参数
         */
        return QueueBuilder.durable(QC_QUEUE)
                .deadLetterExchange(Y_DEAD_EXCHANGE).deadLetterRoutingKey(YD_DEAD_ROUTING_KEY).build();
    }

    /**
     * 普通交换机与普通队列通过QC 普通routingKey 绑定
     *
     * @param queueC
     * @param xExchange
     * @return
     */
    @Bean
    public Binding queuecBindingX(@Qualifier("queueC") Queue queueC, @Qualifier("xExchange") DirectExchange xExchange) {
        return BindingBuilder.bind(queueC).to(xExchange).with(XC_ROUTING_KEY);
    }


}
